package com.songyang.yougnsql.config;

import com.songyang.yougnsql.common.ErrorMsg;
import com.songyang.yougnsql.common.ExceptionHandler;
import com.songyang.yougnsql.common.YoungSQLException;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

/**
 * @ClassName Config
 * @Description 读取数据库配置文件类
 * @date 2022/12/27 17:57
 * @Author yanceysong
 * @Version 1.0
 */
public class Config {
    /**
     * 需要对数据检查的字段集合
     */
    private static final Set<String> needCheckIsNum = new HashSet<>();
    /**
     * 配置文件映射
     */
    private static Map<String, Object> configMap = new HashMap<>();

    static {
        needCheckIsNum.add(ConfigConst.SQL_CACHE_LIMIT);
        needCheckIsNum.add(ConfigConst.CORE_DATA_CACHE_LIMIT);
        needCheckIsNum.add(ConfigConst.ENCODER_TYPE);
    }

    /**
     * 读取配置文件
     *
     * @param configFilePath 配置文件路径
     * @return key-value键值对
     */
    private static Map<String, Object> readConfig(String configFilePath) {
        Properties properties = loadConfig(configFilePath);
        HashMap<String, Object> map = new HashMap<String, Object>((Map) properties);
        try {
            if (!checkConfig(map)) {
                throw new YoungSQLException(ErrorMsg.CONFIG_PARAM_ILLEGAL);
            }
        } catch (YoungSQLException e) {
            ExceptionHandler.handler(e);
        }
        return map;
    }

    /**
     * 加载配置文件
     *
     * @param path 配置文件路径
     */
    private static Properties loadConfig(String path) {
        Properties properties = new Properties();
        BufferedReader bufferedReader;
        try {
            bufferedReader = new BufferedReader(new FileReader(path));
            properties.load(bufferedReader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }

    /**
     * 初始化配置文件
     *
     * @param path 配置文件路径
     */
    public static void initConfig(String path) {
        if (configMap == null || configMap.size() == 0) {
            configMap = readConfig(path);
        }
    }

    /**
     * 获取配置文件的对外方法
     *
     * @param key key
     * @return 值
     */
    public static Object getConfig(String key) {
        return configMap.getOrDefault(key,ConfigConst.CONFIG_DEFAULT_MAP.get(key));
    }

    /**
     * 检查配置文件是否合乎规范
     *
     * @param configMap 配置文件
     * @return 结果
     */
    private static boolean checkConfig(Map configMap) throws YoungSQLException {
        try {
            boolean result;
            for (Object key : configMap.keySet()) {
                Object config = configMap.get((String) key);
                result = checkResultString(config) &&  (!needCheckIsNum.contains((String) config) || checkResultNum(config));
                if (!result) return false;
            }
            return true;
        } catch (Exception e) {
            throw new YoungSQLException(ErrorMsg.PARAM_ILLEGAL_EXCEPTION);
        }
    }


    /**
     * 检查一个参数是否是正常的数字
     *
     * @param o 获取的配置文件结果
     * @return 检查结果
     */
    private static boolean checkResultNum(Object o) {
        try {
            return checkResultString(o) && (Long.parseLong((String) o) < Long.MAX_VALUE);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 检查一个参数是否是正常的字符串
     *
     * @param o 获取的配置文件结果
     * @return 检查结果
     */
    private static boolean checkResultString(Object o) {
        try {
            return (String) o != null && !String.valueOf(o).equals("");
        } catch (Exception e) {
            return false;
        }
    }
}
